/*
 * AccessCheck.c
 *
 *  Created on: 2011-7-23
 *      Author: gexiao
 */
/*
 * Check access to fields and methods.
 */
#include "../Dalvik.h"

/*
 * Return the #of initial characters that match.
 */
static int strcmpCount(const char* str1, const char* str2) {
	int count = 0;

	while (true) {
		char ch = str1[count];
		if (ch == '\0' || ch != str2[count])
			return count;
		count++;
	}
}

/*
 * Returns "true" if the two classes are in the same runtime package.
 */bool dvmInSamePackage(const ClassObject* class1, const ClassObject* class2) {
	//quick test for intra-class access
	if (class1 == class2)
		return true;

	//class loaders must match
	if (class1->classLoader != class2->classLoader)
		return false;

	/*
	 * Switch array classes to their element types. Arrays receive the
	 * class loader of the underlying element type. The point of doing
	 * this is to get the un-decorated class name, without all the
	 * "[[L..." stuff.
	 */
	if (dvmIsArrayClass(class1))
		class1 = class1->elementClass;
	if (dvmIsArrayClass(class2))
		class2 = class2->elementClass;

	//check again
	if (class1 == class2)
		return true;

	/*
	 * We have two classes with different names. Compare them and see
	 * if they match up through the final '/'.
	 *
	 * 	Ljava/lang/Object; + Ljava/lang/Class;	--> true
	 * 	LFoo;			   + LBar;				--> true
	 * 	Ljava/lang/Object; + Ljava/io/File;		--> false
	 * 	Ljava/lang/Object; + Ljava/lang/reflect/Method; -->false
	 */
	int commonLen;

	commonLen = strcmpCount(class1->descriptor, class2->descriptor);
	if (strchr(class1->descriptor + commonLen, '/') != NULL || strchr(
			class2->descriptor + commonLen, '/') != NULL) {
		return false;
	}
	return true;
}

/*
 * Determine whether the "accessFrom" class is allowed to get at "clazz".
 *
 * It's allowed if "clazz" is public or is in the same package. (Only
 * inner classes can marked "private" or "protected", so we don't need
 * to check for it here.)
 */bool dvmCheckClassAccess(const ClassObject* accessFrom,
		const ClassObject* clazz) {
	if (dvmIsPublicClass(clazz))
		return true;
	return dvmInSamePackage(accessFrom, clazz);
}

/*
 *
 */
 bool dvmCheckMethodAccess(const ClassObject* accessFrom, const Method* method) {

}
